package org.convallaria.system.biz.service.impl;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.convallaria.system.biz.service.RiskDetectionService;
import org.convallaria.system.biz.service.SecurityMonitoringService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 风险用户检测服务实现类
 * 
 * @author convallaria
 * @since 1.0.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RiskDetectionServiceImpl implements RiskDetectionService {

    private final RedisTemplate<String, Object> redisTemplate;
    private final SecurityMonitoringService securityMonitoringService;
    
    private static final String USER_RISK_PREFIX = "risk:user:";
    private static final String USER_BEHAVIOR_PREFIX = "behavior:user:";
    private static final String RISK_CONFIG_KEY = "risk:config:detection";
    private static final String OPERATION_COUNT_PREFIX = "operation:count:";

    @Override
    public Map<String, Object> analyzeUserRisk(Long userId) {
        Map<String, Object> riskAnalysis = new HashMap<>();
        
        try {
            // 获取用户风险评分
            int riskScore = getUserRiskScore(userId);
            riskAnalysis.put("riskScore", riskScore);
            
            // 确定风险等级
            String riskLevel = determineRiskLevel(riskScore);
            riskAnalysis.put("riskLevel", riskLevel);
            
            // 分析登录行为
            Map<String, Object> loginAnalysis = analyzeLoginBehavior(userId);
            riskAnalysis.put("loginAnalysis", loginAnalysis);
            
            // 分析操作行为
            Map<String, Object> operationAnalysis = analyzeOperationBehavior(userId);
            riskAnalysis.put("operationAnalysis", operationAnalysis);
            
            // 分析权限使用
            Map<String, Object> permissionAnalysis = analyzePermissionUsage(userId);
            riskAnalysis.put("permissionAnalysis", permissionAnalysis);
            
            // 分析时间模式
            Map<String, Object> timePatternAnalysis = analyzeTimePattern(userId);
            riskAnalysis.put("timePatternAnalysis", timePatternAnalysis);
            
            // 生成风险建议
            List<String> recommendations = generateRiskRecommendations(riskAnalysis);
            riskAnalysis.put("recommendations", recommendations);
            
            // 记录风险分析事件
            if ("HIGH".equals(riskLevel) || "CRITICAL".equals(riskLevel)) {
                securityMonitoringService.recordSecurityEvent("HIGH_RISK_USER", userId, null, 
                    "用户风险等级: " + riskLevel + ", 评分: " + riskScore, riskLevel);
            }
            
        } catch (Exception e) {
            log.error("分析用户风险失败: userId={}", userId, e);
            riskAnalysis.put("error", "风险分析失败");
        }
        
        return riskAnalysis;
    }

    @Override
    public Map<String, Object> detectAbnormalLogin(Long userId, String ip, String userAgent, LocalDateTime loginTime) {
        Map<String, Object> detection = new HashMap<>();
        
        try {
            List<String> anomalies = new ArrayList<>();
            int riskScore = 0;
            
            // 检查IP异常
            String ipKey = USER_BEHAVIOR_PREFIX + userId + ":ip";
            String lastIp = (String) redisTemplate.opsForValue().get(ipKey);
            if (lastIp != null && !lastIp.equals(ip)) {
                anomalies.add("IP地址变更");
                riskScore += 20;
            }
            
            // 检查用户代理异常
            String uaKey = USER_BEHAVIOR_PREFIX + userId + ":ua";
            String lastUserAgent = (String) redisTemplate.opsForValue().get(uaKey);
            if (lastUserAgent != null && !lastUserAgent.equals(userAgent)) {
                anomalies.add("用户代理变更");
                riskScore += 15;
            }
            
            // 检查登录时间异常
            int hour = loginTime.getHour();
            if (hour >= 2 && hour <= 6) {
                anomalies.add("异常时间登录");
                riskScore += 25;
            }
            
            // 检查登录频率异常
            String loginCountKey = "login:count:" + userId + ":" + loginTime.toLocalDate();
            Integer loginCount = (Integer) redisTemplate.opsForValue().get(loginCountKey);
            if (loginCount == null) {
                loginCount = 0;
            }
            loginCount++;
            redisTemplate.opsForValue().set(loginCountKey, loginCount, 1, TimeUnit.DAYS);
            
            if (loginCount > 10) {
                anomalies.add("登录频率过高");
                riskScore += 30;
            }
            
            // 检查地理位置异常（简化处理）
            String geoKey = USER_BEHAVIOR_PREFIX + userId + ":geo";
            String lastGeo = (String) redisTemplate.opsForValue().get(geoKey);
            if (lastGeo != null && !lastGeo.equals(ip)) {
                // 这里简化处理，实际应该根据IP地理位置判断
                anomalies.add("地理位置异常");
                riskScore += 35;
            }
            
            // 更新用户行为记录
            redisTemplate.opsForValue().set(ipKey, ip, 30, TimeUnit.DAYS);
            redisTemplate.opsForValue().set(uaKey, userAgent, 30, TimeUnit.DAYS);
            redisTemplate.opsForValue().set(geoKey, ip, 30, TimeUnit.DAYS);
            
            detection.put("anomalies", anomalies);
            detection.put("riskScore", riskScore);
            detection.put("isAbnormal", !anomalies.isEmpty());
            detection.put("riskLevel", determineRiskLevel(riskScore));
            
            // 如果检测到异常，记录安全事件
            if (!anomalies.isEmpty()) {
                securityMonitoringService.recordSecurityEvent("ABNORMAL_LOGIN", userId, ip, 
                    "异常登录检测: " + String.join(", ", anomalies), 
                    riskScore > 50 ? "HIGH" : "MEDIUM");
            }
            
        } catch (Exception e) {
            log.error("检测异常登录失败: userId={}, ip={}", userId, ip, e);
            detection.put("error", "异常登录检测失败");
        }
        
        return detection;
    }

    @Override
    public Map<String, Object> detectAbnormalOperation(Long userId, String operation, String resource, LocalDateTime timestamp) {
        Map<String, Object> detection = new HashMap<>();
        
        try {
            List<String> anomalies = new ArrayList<>();
            int riskScore = 0;
            
            // 检查操作频率
            String operationKey = OPERATION_COUNT_PREFIX + userId + ":" + operation;
            Integer operationCount = (Integer) redisTemplate.opsForValue().get(operationKey);
            if (operationCount == null) {
                operationCount = 0;
            }
            operationCount++;
            redisTemplate.opsForValue().set(operationKey, operationCount, 1, TimeUnit.HOURS);
            
            if (operationCount > 100) {
                anomalies.add("操作频率过高");
                riskScore += 40;
            }
            
            // 检查批量操作
            String batchKey = "batch:operation:" + userId + ":" + timestamp.toLocalDate();
            Integer batchCount = (Integer) redisTemplate.opsForValue().get(batchKey);
            if (batchCount == null) {
                batchCount = 0;
            }
            batchCount++;
            redisTemplate.opsForValue().set(batchKey, batchCount, 1, TimeUnit.DAYS);
            
            if (batchCount > 1000) {
                anomalies.add("批量操作异常");
                riskScore += 50;
            }
            
            // 检查敏感操作
            List<String> sensitiveOperations = Arrays.asList("DELETE", "UPDATE", "GRANT", "REVOKE");
            if (sensitiveOperations.contains(operation.toUpperCase())) {
                anomalies.add("敏感操作");
                riskScore += 30;
            }
            
            // 检查异常时间操作
            int hour = timestamp.getHour();
            if (hour >= 22 || hour <= 6) {
                anomalies.add("异常时间操作");
                riskScore += 20;
            }
            
            detection.put("anomalies", anomalies);
            detection.put("riskScore", riskScore);
            detection.put("isAbnormal", !anomalies.isEmpty());
            detection.put("riskLevel", determineRiskLevel(riskScore));
            
            // 如果检测到异常，记录安全事件
            if (!anomalies.isEmpty()) {
                securityMonitoringService.recordSecurityEvent("ABNORMAL_OPERATION", userId, null, 
                    "异常操作检测: " + String.join(", ", anomalies), 
                    riskScore > 50 ? "HIGH" : "MEDIUM");
            }
            
        } catch (Exception e) {
            log.error("检测异常操作失败: userId={}, operation={}", userId, operation, e);
            detection.put("error", "异常操作检测失败");
        }
        
        return detection;
    }

    @Override
    public String getUserRiskLevel(Long userId) {
        try {
            int riskScore = getUserRiskScore(userId);
            return determineRiskLevel(riskScore);
        } catch (Exception e) {
            log.error("获取用户风险等级失败: userId={}", userId, e);
            return "MEDIUM";
        }
    }

    @Override
    public List<Map<String, Object>> getHighRiskUsers(int limit) {
        List<Map<String, Object>> highRiskUsers = new ArrayList<>();
        
        try {
            String pattern = USER_RISK_PREFIX + "*";
            Set<String> keys = redisTemplate.keys(pattern);
            
            if (keys != null) {
                List<Map<String, Object>> allUsers = new ArrayList<>();
                
                for (String key : keys) {
                    Map<String, Object> userRisk = (Map<String, Object>) redisTemplate.opsForValue().get(key);
                    if (userRisk != null) {
                        String riskLevel = (String) userRisk.get("riskLevel");
                        if ("HIGH".equals(riskLevel) || "CRITICAL".equals(riskLevel)) {
                            allUsers.add(userRisk);
                        }
                    }
                }
                
                // 按风险评分排序
                allUsers.sort((a, b) -> {
                    Integer scoreA = (Integer) a.get("riskScore");
                    Integer scoreB = (Integer) b.get("riskScore");
                    return scoreB.compareTo(scoreA);
                });
                
                // 限制返回数量
                int count = Math.min(limit, allUsers.size());
                for (int i = 0; i < count; i++) {
                    highRiskUsers.add(allUsers.get(i));
                }
            }
            
        } catch (Exception e) {
            log.error("获取高风险用户失败", e);
        }
        
        return highRiskUsers;
    }

    @Override
    public void updateUserRiskScore(Long userId, int riskScore, String reason) {
        try {
            String key = USER_RISK_PREFIX + userId;
            Map<String, Object> riskInfo = new HashMap<>();
            riskInfo.put("userId", userId);
            riskInfo.put("riskScore", riskScore);
            riskInfo.put("riskLevel", determineRiskLevel(riskScore));
            riskInfo.put("updateTime", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
            riskInfo.put("reason", reason);
            
            redisTemplate.opsForValue().set(key, riskInfo, 7, TimeUnit.DAYS);
            
            log.info("用户风险评分已更新: userId={}, score={}, level={}, reason={}", 
                    userId, riskScore, determineRiskLevel(riskScore), reason);
            
        } catch (Exception e) {
            log.error("更新用户风险评分失败: userId={}", userId, e);
        }
    }

    @Override
    public Map<String, Object> getUserBehaviorPattern(Long userId) {
        Map<String, Object> pattern = new HashMap<>();
        
        try {
            // 分析登录时间模式
            Map<String, Object> loginTimePattern = analyzeLoginTimePattern(userId);
            pattern.put("loginTimePattern", loginTimePattern);
            
            // 分析操作模式
            Map<String, Object> operationPattern = analyzeOperationPattern(userId);
            pattern.put("operationPattern", operationPattern);
            
            // 分析IP使用模式
            Map<String, Object> ipPattern = analyzeIpPattern(userId);
            pattern.put("ipPattern", ipPattern);
            
            // 分析权限使用模式
            Map<String, Object> permissionPattern = analyzePermissionPattern(userId);
            pattern.put("permissionPattern", permissionPattern);
            
        } catch (Exception e) {
            log.error("获取用户行为模式失败: userId={}", userId, e);
            pattern.put("error", "获取行为模式失败");
        }
        
        return pattern;
    }

    @Override
    public Map<String, Object> detectBatchOperationRisk(Long userId, int operationCount, int timeWindow) {
        Map<String, Object> detection = new HashMap<>();
        
        try {
            String key = "batch:risk:" + userId + ":" + System.currentTimeMillis() / (timeWindow * 60000);
            Integer currentCount = (Integer) redisTemplate.opsForValue().get(key);
            if (currentCount == null) {
                currentCount = 0;
            }
            currentCount += operationCount;
            redisTemplate.opsForValue().set(key, currentCount, timeWindow, TimeUnit.MINUTES);
            
            boolean isRisky = currentCount > 500; // 阈值可配置
            int riskScore = isRisky ? 80 : 20;
            
            detection.put("isRisky", isRisky);
            detection.put("riskScore", riskScore);
            detection.put("operationCount", currentCount);
            detection.put("timeWindow", timeWindow);
            detection.put("riskLevel", determineRiskLevel(riskScore));
            
            if (isRisky) {
                securityMonitoringService.recordSecurityEvent("BATCH_OPERATION_RISK", userId, null, 
                    "批量操作风险: " + currentCount + "次操作/" + timeWindow + "分钟", "HIGH");
            }
            
        } catch (Exception e) {
            log.error("检测批量操作风险失败: userId={}", userId, e);
            detection.put("error", "批量操作风险检测失败");
        }
        
        return detection;
    }

    @Override
    public Map<String, Object> detectPermissionAbuseRisk(Long userId, List<String> permissions) {
        Map<String, Object> detection = new HashMap<>();
        
        try {
            List<String> suspiciousPermissions = new ArrayList<>();
            int riskScore = 0;
            
            // 检查敏感权限
            List<String> sensitivePermissions = Arrays.asList("ADMIN", "SUPER_USER", "DELETE_ALL", "GRANT_ALL");
            for (String permission : permissions) {
                if (sensitivePermissions.contains(permission)) {
                    suspiciousPermissions.add(permission);
                    riskScore += 30;
                }
            }
            
            // 检查权限数量
            if (permissions.size() > 50) {
                suspiciousPermissions.add("权限数量过多");
                riskScore += 25;
            }
            
            // 检查权限组合
            if (permissions.contains("READ") && permissions.contains("DELETE") && permissions.contains("GRANT")) {
                suspiciousPermissions.add("危险权限组合");
                riskScore += 40;
            }
            
            detection.put("suspiciousPermissions", suspiciousPermissions);
            detection.put("riskScore", riskScore);
            detection.put("isAbusive", !suspiciousPermissions.isEmpty());
            detection.put("riskLevel", determineRiskLevel(riskScore));
            
            if (!suspiciousPermissions.isEmpty()) {
                securityMonitoringService.recordSecurityEvent("PERMISSION_ABUSE_RISK", userId, null, 
                    "权限滥用风险: " + String.join(", ", suspiciousPermissions), "HIGH");
            }
            
        } catch (Exception e) {
            log.error("检测权限滥用风险失败: userId={}", userId, e);
            detection.put("error", "权限滥用风险检测失败");
        }
        
        return detection;
    }

    @Override
    public Map<String, Object> getRiskDetectionConfig() {
        try {
            Map<String, Object> config = (Map<String, Object>) redisTemplate.opsForValue().get(RISK_CONFIG_KEY);
            if (config == null) {
                // 返回默认配置
                config = new HashMap<>();
                config.put("enableRealTimeDetection", true);
                config.put("riskScoreThreshold", 70);
                config.put("batchOperationThreshold", 500);
                config.put("sensitiveOperationWeight", 30);
                config.put("timeWindowMinutes", 60);
            }
            return config;
        } catch (Exception e) {
            log.error("获取风险检测配置失败", e);
            return new HashMap<>();
        }
    }

    @Override
    public void updateRiskDetectionConfig(Map<String, Object> config) {
        try {
            redisTemplate.opsForValue().set(RISK_CONFIG_KEY, config);
            log.info("风险检测配置已更新: {}", config);
        } catch (Exception e) {
            log.error("更新风险检测配置失败", e);
        }
    }

    @Override
    public Map<String, Object> generateRiskReport(Long userId, LocalDateTime startTime, LocalDateTime endTime) {
        Map<String, Object> report = new HashMap<>();
        
        try {
            // 生成风险报告
            report.put("userId", userId);
            report.put("reportTime", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
            report.put("timeRange", startTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) + " - " + 
                      endTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
            
            // 风险分析
            Map<String, Object> riskAnalysis = analyzeUserRisk(userId);
            report.put("riskAnalysis", riskAnalysis);
            
            // 行为模式
            Map<String, Object> behaviorPattern = getUserBehaviorPattern(userId);
            report.put("behaviorPattern", behaviorPattern);
            
            // 风险建议
            List<String> recommendations = generateRiskRecommendations(riskAnalysis);
            report.put("recommendations", recommendations);
            
        } catch (Exception e) {
            log.error("生成风险报告失败: userId={}", userId, e);
            report.put("error", "生成风险报告失败");
        }
        
        return report;
    }

    @Override
    public Map<String, Object> getSystemRiskOverview() {
        Map<String, Object> overview = new HashMap<>();
        
        try {
            // 获取高风险用户数量
            List<Map<String, Object>> highRiskUsers = getHighRiskUsers(100);
            overview.put("highRiskUserCount", highRiskUsers.size());
            
            // 获取系统风险评分
            int systemRiskScore = calculateSystemRiskScore();
            overview.put("systemRiskScore", systemRiskScore);
            overview.put("systemRiskLevel", determineRiskLevel(systemRiskScore));
            
            // 获取风险趋势
            Map<String, Object> riskTrend = calculateRiskTrend();
            overview.put("riskTrend", riskTrend);
            
        } catch (Exception e) {
            log.error("获取系统风险概览失败", e);
            overview.put("error", "获取系统风险概览失败");
        }
        
        return overview;
    }

    // 私有辅助方法

    private int getUserRiskScore(Long userId) {
        try {
            String key = USER_RISK_PREFIX + userId;
            Map<String, Object> riskInfo = (Map<String, Object>) redisTemplate.opsForValue().get(key);
            if (riskInfo != null) {
                return (Integer) riskInfo.get("riskScore");
            }
            return 50; // 默认中等风险
        } catch (Exception e) {
            log.error("获取用户风险评分失败: userId={}", userId, e);
            return 50;
        }
    }

    private String determineRiskLevel(int riskScore) {
        if (riskScore >= 80) return "CRITICAL";
        if (riskScore >= 60) return "HIGH";
        if (riskScore >= 40) return "MEDIUM";
        return "LOW";
    }

    private Map<String, Object> analyzeLoginBehavior(Long userId) {
        Map<String, Object> analysis = new HashMap<>();
        // 实现登录行为分析逻辑
        analysis.put("loginFrequency", "正常");
        analysis.put("loginTimePattern", "正常");
        analysis.put("ipStability", "稳定");
        return analysis;
    }

    private Map<String, Object> analyzeOperationBehavior(Long userId) {
        Map<String, Object> analysis = new HashMap<>();
        // 实现操作行为分析逻辑
        analysis.put("operationFrequency", "正常");
        analysis.put("operationType", "正常");
        analysis.put("operationTime", "正常");
        return analysis;
    }

    private Map<String, Object> analyzePermissionUsage(Long userId) {
        Map<String, Object> analysis = new HashMap<>();
        // 实现权限使用分析逻辑
        analysis.put("permissionCount", "正常");
        analysis.put("permissionType", "正常");
        analysis.put("permissionUsage", "正常");
        return analysis;
    }

    private Map<String, Object> analyzeTimePattern(Long userId) {
        Map<String, Object> analysis = new HashMap<>();
        // 实现时间模式分析逻辑
        analysis.put("activeHours", "正常");
        analysis.put("weekendActivity", "正常");
        analysis.put("holidayActivity", "正常");
        return analysis;
    }

    private List<String> generateRiskRecommendations(Map<String, Object> riskAnalysis) {
        List<String> recommendations = new ArrayList<>();
        
        String riskLevel = (String) riskAnalysis.get("riskLevel");
        if ("HIGH".equals(riskLevel) || "CRITICAL".equals(riskLevel)) {
            recommendations.add("建议加强用户监控");
            recommendations.add("建议限制用户权限");
            recommendations.add("建议要求用户重新认证");
        }
        
        return recommendations;
    }

    private Map<String, Object> analyzeLoginTimePattern(Long userId) {
        Map<String, Object> pattern = new HashMap<>();
        // 实现登录时间模式分析
        pattern.put("peakHours", Arrays.asList(9, 10, 14, 15));
        pattern.put("weekendActivity", "低");
        return pattern;
    }

    private Map<String, Object> analyzeOperationPattern(Long userId) {
        Map<String, Object> pattern = new HashMap<>();
        // 实现操作模式分析
        pattern.put("commonOperations", Arrays.asList("READ", "UPDATE"));
        pattern.put("operationFrequency", "正常");
        return pattern;
    }

    private Map<String, Object> analyzeIpPattern(Long userId) {
        Map<String, Object> pattern = new HashMap<>();
        // 实现IP模式分析
        pattern.put("ipStability", "稳定");
        pattern.put("ipCount", 1);
        return pattern;
    }

    private Map<String, Object> analyzePermissionPattern(Long userId) {
        Map<String, Object> pattern = new HashMap<>();
        // 实现权限模式分析
        pattern.put("permissionCount", 10);
        pattern.put("permissionTypes", Arrays.asList("READ", "UPDATE"));
        return pattern;
    }

    private int calculateSystemRiskScore() {
        // 实现系统风险评分计算
        return 60; // 示例值
    }

    private Map<String, Object> calculateRiskTrend() {
        Map<String, Object> trend = new HashMap<>();
        // 实现风险趋势计算
        trend.put("trend", "上升");
        trend.put("changeRate", 5.2);
        return trend;
    }
}
